package cn.source.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.source.common.utils.DateUtils;
import cn.source.common.utils.StringUtils;
import cn.source.system.domain.DeyuLogEntry;
import cn.source.system.domain.DeyuLogFile;
import cn.source.system.mapper.DeyuLogFileMapper;
import cn.source.system.service.IDeyuLogFileService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 日志文件Service业务层处理
 * 
 * @author deyucare.com
 * @date 2025-03-05
 */
@Service
public class DeyuLogFileServiceImpl implements IDeyuLogFileService 
{
    private static final Logger log = LoggerFactory.getLogger(DeyuLogFileServiceImpl.class);

    @Autowired
    private DeyuLogFileMapper deyuLogFileMapper;

    /**
     * 查询日志文件
     * 
     * @param id 日志文件主键
     * @return 日志文件
     */
    @Override
    public DeyuLogFile selectDeyuLogFileById(Long id)
    {
        return deyuLogFileMapper.selectDeyuLogFileById(id);
    }

    /**
     * 查询日志文件列表
     * 
     * @param deyuLogFile 日志文件
     * @return 日志文件
     */
    @Override
    public List<DeyuLogFile> selectDeyuLogFileList(DeyuLogFile deyuLogFile)
    {
        return deyuLogFileMapper.selectDeyuLogFileList(deyuLogFile);
    }

    /**
     * 新增日志文件
     * 
     * @param deyuLogFile 日志文件
     * @return 结果
     */
    @Transactional
    @Override
    public int insertDeyuLogFile(DeyuLogFile deyuLogFile)
    {
        deyuLogFile.setCreateTime(DateUtils.getNowDate());
        int rows = deyuLogFileMapper.insertDeyuLogFile(deyuLogFile);
        insertDeyuLogEntry(deyuLogFile);
        return rows;
    }

    /**
     * 修改日志文件
     * 
     * @param deyuLogFile 日志文件
     * @return 结果
     */
    @Transactional
    @Override
    public int updateDeyuLogFile(DeyuLogFile deyuLogFile)
    {
        deyuLogFile.setUpdateTime(DateUtils.getNowDate());
        deyuLogFileMapper.deleteDeyuLogEntryByLogFileId(deyuLogFile.getId());
        insertDeyuLogEntry(deyuLogFile);
        return deyuLogFileMapper.updateDeyuLogFile(deyuLogFile);
    }

    /**
     * 批量删除日志文件
     * 
     * @param ids 需要删除的日志文件主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteDeyuLogFileByIds(Long[] ids)
    {
        deyuLogFileMapper.deleteDeyuLogEntryByLogFileIds(ids);
        return deyuLogFileMapper.deleteDeyuLogFileByIds(ids);
    }

    /**
     * 删除日志文件信息
     * 
     * @param id 日志文件主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteDeyuLogFileById(Long id)
    {
        deyuLogFileMapper.deleteDeyuLogEntryByLogFileId(id);
        return deyuLogFileMapper.deleteDeyuLogFileById(id);
    }

    /**
     * 新增日志信息信息
     * 
     * @param deyuLogFile 日志文件对象
     */
    public void insertDeyuLogEntry(DeyuLogFile deyuLogFile)
    {
        List<DeyuLogEntry> deyuLogEntryList = deyuLogFile.getDeyuLogEntryList();
        Long id = deyuLogFile.getId();
        if (StringUtils.isNotNull(deyuLogEntryList))
        {
            List<DeyuLogEntry> list = new ArrayList<DeyuLogEntry>();
            for (DeyuLogEntry deyuLogEntry : deyuLogEntryList)
            {
                deyuLogEntry.setLogFileId(id);
                list.add(deyuLogEntry);
            }
            if (list.size() > 0)
            {
                deyuLogFileMapper.batchDeyuLogEntry(list);
            }
        }
    }

    @Override
    @Async
    public void processLogFile(MultipartFile file, Long userId, String deviceMac) {
        try {
            // 保存文件元数据
            Date nowDate = DateUtils.getNowDate();
            DeyuLogFile deyuLogFile = new DeyuLogFile();
            deyuLogFile.setFileName(file.getOriginalFilename());
            deyuLogFile.setCreateTime(nowDate);
            deyuLogFile.setFileSizeMb(BigDecimal.valueOf(file.getSize() / 1024.0 / 1024.0));
            deyuLogFile.setUserId(userId);
            deyuLogFile.setDeviceMac(deviceMac);
            deyuLogFileMapper.insertDeyuLogFile(deyuLogFile);

            // 解析日志内容
            ArrayList<DeyuLogEntry> deyuLogEntryList = new ArrayList<>();
            BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                DeyuLogEntry deyuLogEntry = parseLine(line); // 解析每行日志
                if (deyuLogEntry != null) {
                    deyuLogEntry.setLogFileId(deyuLogFile.getId());
                    deyuLogEntry.setCreateTime(nowDate);
                    deyuLogEntryList.add(deyuLogEntry);
                }
            }
            deyuLogFileMapper.batchDeyuLogEntry(deyuLogEntryList);
        } catch (IOException e) {
            log.error("解析保存日志异常: {0}", e);
        }
    }

    @Override
    public List<DeyuLogEntry> selectByLogFileId(DeyuLogEntry deyuLogEntry) {
        return deyuLogFileMapper.selectByLogFileId(deyuLogEntry);
    }

    private DeyuLogEntry parseLine(String line) {
        // 解析日志行，提取时间、级别、消息
        // 示例正则：2025-03-03 16:46:11 [INFO]: Starting health system...
        Pattern pattern = Pattern.compile("^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\[([A-Z]+)]: (.*)$");
        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            DeyuLogEntry entry = new DeyuLogEntry();
            entry.setLogTime(DateUtil.parse(matcher.group(1),"yyyy-MM-dd HH:mm:ss"));
            entry.setLogLevel(matcher.group(2));
            entry.setMessage(matcher.group(3));
            return entry;
        }
        return null;
    }
}
